package net.jxta.myjxta.util;

import net.jxta.myjxta.MyJXTA;
import net.jxta.myjxta.search.AbstractSearchListener;
import net.jxta.myjxta.search.SearchModifier;
import net.jxta.myjxta.search.Searcher;
import net.jxta.myjxta.util.objectmodel.JxtaNode;

import java.util.WeakHashMap;

/**
 * Provides a mechanism to search a PeerNode Control-Pipe based on the pipeID
 * The search will only be executed if no pipesearch was started in the last 30 seconds
 * If the pipe is found the corresponding PeerNode is added to the MyJxta Object Repository
 */
public final class RateLimitedOriginatorSearcher {
    private static final WeakHashMap<KeyPair, Long> shortTermMemory = new WeakHashMap<KeyPair, Long>();
    private final Group searcherGroup;
    private final MyJXTA m_myjxta;
    private static final int SEARCH_MEMORY_TIMEOUT_MS = 30000;

    public RateLimitedOriginatorSearcher(Group p_group,MyJXTA _myjxta) {
        searcherGroup=p_group;
        m_myjxta=_myjxta;
    }

    /**
     *
     * @param peerName
     * @return true if a search for the given peerName was executed during the last X seconds
     */
    public boolean searchedRecently(String peerName) {
    	peerName=peerName.trim();
        Long lastSearch=shortTermMemory.get(new KeyPair(peerName,searcherGroup));
        if (lastSearch==null)
            return false;
        long deltaT = System.currentTimeMillis() - lastSearch.longValue();
        if (deltaT <SEARCH_MEMORY_TIMEOUT_MS){
//            System.out.println("seached recently for "+peerName+".. dont start a new search");
            return true;
        } else {
            return false; //no search in the last 10secondsx
        }
    }

    public void search(String searchedPeerName) {
    	searchedPeerName = searchedPeerName.trim();
        shortTermMemory.put(new KeyPair(searchedPeerName,searcherGroup) ,new Long(System.currentTimeMillis()));
        final Searcher searcher = new Searcher(Searcher.PIPE, searcherGroup,m_myjxta);
        SearchModifier modifier = new SearchModifier(SearchModifier.EQUALITY);

        searcher.addListener(new AbstractSearchListener() {
             public void add(JxtaNode node) {
                 m_myjxta.addJxtaNode(node);
                 searcher.stop();
             }
         });
//        System.out.println("starting search for groupchat member "+searchedPeerName);
        searcher.start(modifier.createTerm(searchedPeerName));
    }

    public void removeFromMemory(String peerName) {
         shortTermMemory.remove(new KeyPair(peerName,searcherGroup));
    }


    private class KeyPair {
        private final Object o1;
        private final Object o2;

        public KeyPair(Object p_o1, Object p_o2) {
            o1 = p_o1;
            o2 = p_o2;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            final KeyPair keyPair = (KeyPair) o;

            if (!o1.equals(keyPair.o1)) return false;
            if (!o2.equals(keyPair.o2)) return false;

            return true;
        }

        public int hashCode() {
            int result;
            result = o1.hashCode();
            result = 29 * result + o2.hashCode();
            return result;
        }
    }
}
